<!-- 电子签名 -->
<template>
	<view class='signature'>
		<view class="drawing">
			<canvas class="sign-canvas" :style="{width: width+'px',height: height+'px'}" canvas-id="signCanvas" @touchmove='move'
			 @touchstart='start($event)' @touchend='end' @touchcancel='cancel' @longtap='tapLong' disable-scroll='true' @error='error'></canvas>
		</view>
		<view class="right">
			<image v-if="image!=''" class="sign-image" :src="image" mode="aspectFit"></image>
			<view v-else class="no-sign">
				<text>未签名</text>
			</view>
			<view class="btn">
				<text class="btn-resign" @tap="tapAgainSign">重签</text>
				<text class="btn-save" @tap="tapSaveSign">保存</text>
			</view>
		</view>
	</view>
</template>

<script>
	let ctx = null;

	var touchs = [];
	export default {
		props: {
			value: {
				type: String,
				default: ''
			}
		},
		data() {
			return {
				isSign: false, //是否签名
				width: 0,
				height: 0,
				image: '',
				index: 0
			}
		},
		created() {
			const systemInfo = uni.getSystemInfoSync();
			console.log(systemInfo);
			if (systemInfo.platform == 'android') {
				this.height = systemInfo.screenWidth - 44 - systemInfo.statusBarHeight;
				this.width = systemInfo.screenHeight - 140;
			} else {
				//横屏
				this.height = systemInfo.screenWidth - 44;
				this.width = systemInfo.screenHeight - 140;
			}
			console.log(`宽：${this.width}高：${this.height}`)

			
		},
		//页面渲染完成
		mounted() {
			ctx = uni.createCanvasContext('signCanvas');
			//设置画布背景色为白色，否则保存的png图片背景为透明
			ctx.rect(0, 0, this.width, this.height)
			ctx.setFillStyle('#FFFFFF')
			ctx.fill()
			ctx.draw(true)
		},
		watch: {
			value(nVal, oVal) {
				this.image = nVal;
			}
		},
		/**
		 * 计算属性
		 */
		computed: {

		},
		methods: {
			//重签
			tapAgainSign() {
				//console.log('清除画布');
				//清除画布
				ctx.clearRect(0, 0, this.width, this.height)
				ctx.rect(0, 0, this.width, this.height)
				ctx.setFillStyle('#FFFFFF')
				ctx.fill()
				ctx.draw(true)
				touchs = [];
				//设置为未签名
				this.isSign = false;
			},
			//保存签名
			tapSaveSign() {
				//console.log('保存签名');
				let that = this;
				this.isSign = true;
				uni.canvasToTempFilePath({
					x: 0,
					y: 0,
					width: this.width,
					height: this.height,
					destWidth: this.width / 4, //生成画布宽
					destHeight: this.height / 4, //生成画布高
					canvasId: 'signCanvas',
					success: function(res) {
						// 在H5平台下，tempFilePath 为 base64
						//console.log(res.tempFilePath)
						let path = res.tempFilePath;
						that.image = path;
						let bitmap = new plus.nativeObj.Bitmap('userSign');
						bitmap.load(path, function() {
							//图片加载成功
							let base64Img = bitmap.toBase64Data();

							bitmap.recycle(); //回收图片内存

							that.$emit('sign', base64Img);


						}, function(e) {
							//console.log('图片加载失败' + JSON.stringify(e))
							that.$emit('sign', '');
							bitmap.recycle(); //回收图片内存
						})

					}
				})

			},
			// 画布的触摸移动开始手势响应
			start: function(event) {
				// console.log(event)
				//console.log("触摸开始" + event.changedTouches[0].x)
				//console.log("触摸开始" + event.changedTouches[0].y)
				//获取触摸开始的 x,y
				let point = {
					x: event.changedTouches[0].x,
					y: event.changedTouches[0].y
				}
				// console.log(point)
				if (!this.isSign) {
					touchs.push(point);
				}



			},
			// 画布的触摸移动手势响应
			move: function(e) {
				let point = {
					x: e.touches[0].x,
					y: e.touches[0].y
				}
				// console.log(point)
				if (!this.isSign) {
					touchs.push(point)
					this.index++;
					//为了绘制的线平滑，没有锯齿
					if (touchs.length > 2) {
						ctx.beginPath();
						let x1, x2, y1, y2, x, y, cx, cy, t = 0.5;
						let mid = touchs[this.index - 1];//两点之间其中一个点是公式计算点
						let start = touchs[this.index - 2]; //开始点
						let end = touchs[this.index]; //结束点
						x = mid.x;
						y = mid.y;
						x1 = start.x;
						y1 = start.y;
						x2 = end.x;
						y2 = end.y;
						/**
						 * 计算控制点
						 * 计算公式： https://segmentfault.com/a/1190000018597975 
						 * 反推可得下面的计算方法
						 * */
						cx = (x - (1 - t) * (1 - t) * x1 - t * t * x2) / (2 * t * (1 - t));
						cy = (y - (1 - t) * (1 - t) * y1 - t * t * y2) / (2 * t * (1 - t));
						ctx.moveTo(x1, y1);
						ctx.setLineWidth(8);
						// 二阶贝塞尔曲线
						ctx.quadraticCurveTo(cx, cy, x2, y2);
						ctx.stroke();
						/**
						 * uni-app画布的draw()方法:显示内容
						 * this.ctx.draw(reserve,callback);
						 * reserv默认为false，不接着上次绘制；为true则接着上次绘制
						 * */
						ctx.draw(true);
						
						//this.draw(touchs)
					}
				}

			},

			// 画布的触摸移动结束手势响应
			end: function(e) {
				//console.log("触摸结束" + e)
				this.index=0;
				touchs=[];
				// 清空轨迹数组
				// for (let i = 0; i < touchs.length; i++) {
				// 	touchs.pop()
				// }

			},

			// 画布的触摸取消响应
			cancel: function(e) {
				//console.log("触摸取消" + e)
			},

			// 画布的长按手势响应
			tapLong: function(e) {
				//console.log("长按手势" + e)
			},

			error: function(e) {
				//console.log("画布触摸错误" + e)
			},
			//绘制
			draw: function(touchs) {
				//console.log(touchs[0], touchs[1])

				if (!this.isSign) {
					let point1 = touchs[0]
					let point2 = touchs[1]
					touchs.shift()
					ctx.setLineWidth(8);
					ctx.moveTo(point1.x, point1.y)
					ctx.lineTo(point2.x, point2.y)
					ctx.stroke()
					ctx.draw(true)
				}
			}
		}
	}
</script>

<style scoped>
	.signature {
		display: flex;
		justify-content: space-between;
	}

	.drawing {
		background-color: #FFFFFF;
	}

	.sign-canvas {
		background-color: #FFFFFF;
	}

	.right {
		display: flex;
		flex-direction: column;
		justify-content: space-between;
		width: 140px;
		background-color: #EEEEEE;
	}

	.sign-image {
		width: 266upx;
		height: 150upx;
		margin-top: 40upx;
	}

	.no-sign {
		margin-top: 40upx;
		display: flex;
		justify-content: center;
		color: #909399;
		font-size: 28upx;
	}

	.btn {
		display: flex;
		flex-direction: column;
		padding-bottom: 20upx;
	}

	.btn-resign {
		background-color: #FF5722;
		padding: 18upx;
		border-radius: 10upx;
		font-size: 28upx;
		color: #fff;
		margin: 10upx 20upx;
		text-align: center;
	}

	.btn-save {
		background-color: #007AFF;
		padding: 18upx;
		border-radius: 10upx;
		font-size: 28upx;
		color: #fff;
		margin: 10upx 20upx;
		text-align: center;
	}
</style>